package com.jushu.storbox.task.tqueue;

import java.io.File;
import java.util.Random;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;

import com.jushu.storbox.MainFrameActivity;
import com.jushu.storbox.R;
import com.jushu.storbox.ShareDriveApplication;
import com.jushu.storbox.callback.ITCallback;
import com.jushu.storbox.callback.ITCallbackObserver;
import com.jushu.storbox.constant.Constant;
import com.jushu.storbox.constant.ErrorConstant;
import com.jushu.storbox.constant.ReceiverConstent;
import com.jushu.storbox.database.DAOFactory;
import com.jushu.storbox.entities.FileInfo;
import com.jushu.storbox.entities.UploadObject;
import com.jushu.storbox.handler.ClientExceptionRelateHandler;
import com.jushu.storbox.manager.AlbumUploadTaskManager;
import com.jushu.storbox.util.DirectoryUtil;
import com.jushu.storbox.util.LogUtil;
import com.jushu.storbox.util.PublicTools;
import com.jushu.storbox.util.identity.AbsIdentity;
import com.jushu.storbox.util.identity.FileMD5Identity;
import com.jushu.storbox.util.identity.IidentityCallback;
import com.jushu.storbox.util.identity.PartFileMD5Identity;
import com.huawei.sharedrive.sdk.android.exception.ClientException;
import com.huawei.sharedrive.sdk.android.modelV2.request.FileSmartUploadRequestV2;
import com.huawei.sharedrive.sdk.android.modelV2.response.FileInfoResponseV2;
import com.huawei.sharedrive.sdk.android.modelV2.response.FilePreUploadResponseV2;
import com.huawei.sharedrive.sdk.android.modelV2.response.UploadUrlRefreshResponse;
import com.huawei.sharedrive.sdk.android.serviceV2.FileClientV2;
import com.huawei.sharedrive.sdk.android.uploadfile.FileSmartUploadV4;
import com.huawei.sharedrive.sdk.android.uploadfile.UploadCallBackV3;
import com.huawei.sharedrive.sdk.android.util.StringUtil;

public class AlbumUploadTask extends PriorityTask{
	
	private final static String TAG = "UploadTask";
	private Random random;
	private int priority;
	private final String id;
	private Context context;
	private String ownerID;
	private String folderID;
	private String authorization;
	private String filePath;
	private int uploadType;
	private AbsIdentity identityTool = null;
	private FileSmartUploadV4 uploadThread = null;
	private boolean isCancel = false;
	private boolean isStoped = false;
	private String fileEncDir;
	private FileInfo fileinfo;
	
	File uploadFile = null;
	UploadObject uploadInfo = null;
	
	//notifycation
	int notificationID = ShareDriveApplication.getInstance().getNotificationID();
	NotificationManager mNotificationManager = null;
    NotificationCompat.Builder mNotification = null;
	
	UploadCallBackV3 fileUploadCallBackV2 = new UploadCallBackV3() {
		private long oldProgress = 0;
		private long progress = 0;
		private String fileId;
		
		@Override
		public boolean isRecordExistByIdentity(String ownerId, String folderId, String identity) {
			uploadInfo = DAOFactory.instance(context).getUploadFileDao().getUploadFileFileInfoBySha1(identity, folderId, ownerId);
			if(uploadInfo == null || uploadInfo.getTransStatus() == Constant.TRANSLATE_IS_SUCCESS){
				return false;
			} else {
				return true;
			}
		}
		@Override
		public String getFileIdByIdentity(String identity) {
			if(uploadInfo == null){
				return "";
			} else {
				return uploadInfo.getId();
			}
		}
		@Override
		public String getUploadUrlByFileId(String fileId) {
			if(uploadInfo == null){
				return "";
			} else {
				return uploadInfo.getUploadPath();
			}
		}
		@Override
		public void onSuccessRefreshUploadPath(UploadUrlRefreshResponse arg0) {
			if(uploadInfo != null){
				uploadInfo.setUploadPath(arg0.getUploadUrl());
				DAOFactory.instance(context).getUploadFileDao().updateUploadUrl(uploadInfo.getId(), uploadInfo.getOwnerId(), arg0.getUploadUrl());
				fileId = uploadInfo.getId();
			} else {
				DAOFactory.instance(context).getUploadFileDao().updateUploadUrl(fileId, ownerID, arg0.getUploadUrl());
			}
		}
		@Override
		public void onRefreshUploadPathFailure(String identity) {
			DAOFactory.instance(context).getUploadFileDao().deleteFile(fileId, ownerID);
		}
		@Override
		public void onReUploadRetainPartFailure(String identity) {
		}
		@Override
		public void onHistoryFileNotExsits(String identity) {
			DAOFactory.instance(context).getUploadFileDao().deleteFile(fileId, ownerID);
		}
		@Override
		public void onGetFilePartsInfoNotFinishedFailure(String identity) {
			DAOFactory.instance(context).getUploadFileDao().deleteFile(fileId, ownerID);
		}
		
		@Override
		public void onPreUploadSuccess(FilePreUploadResponseV2 fResponse, String identity, String filePath) {
			File file = new File(filePath);
			if(uploadInfo == null){
				uploadInfo = new UploadObject();
			}
			fileId = fResponse.getFileId();
			uploadInfo.setId(fResponse.getFileId());
			uploadInfo.setOwnerBy(ownerID);
			uploadInfo.setIdentity(identity);
			uploadInfo.setName(file.getName());
			uploadInfo.setSize(file.length());
			uploadInfo.setParent(folderID);
			uploadInfo.setLoctPath(filePath);
			uploadInfo.setUploadPath(fResponse.getUploadUrl());
			uploadInfo.setTransStatus(Constant.TRANSLATE_IS_STARTED);
			uploadInfo.setType(uploadType);
			DAOFactory.instance(context).getUploadFileDao().insertFile(uploadInfo);
		}
		@Override
		public void onServerExists(String fileID, String ownerId, FileInfoResponseV2 FileInfoResponse) {
			if(uploadInfo == null) {
				File file = new File(filePath);
				uploadInfo = new UploadObject();
				uploadInfo.setName(file.getName());
				uploadInfo.setLoctPath(filePath);
				uploadInfo.setParent(folderID);
			}
			LogUtil.i(TAG, "[" + filePath + "]onSuccess()");
			AlbumUploadTaskManager.instance().removeTask(AlbumUploadTask.this);
			try {
				if(FileInfoResponse != null) {
					int flag = DAOFactory.instance(context).getFileDao().addIfNotExist(FileInfoResponse);
					if(flag == 0) {
						DirectoryUtil.deleteFileThumbnailPath(context, FileInfoResponse.getOwnerBy(), 
								FileInfoResponse.getId(), FileInfoResponse.getName());
					}
					
					if(uploadInfo == null) {
					} else {
						if(fileID != null && fileID.equals(uploadInfo.getId()) ) {
							LogUtil.e(TAG,"new success fileId not equals old fileId");
						}
						DAOFactory.instance(context).getUploadFileDao().deleteFile(uploadInfo.getId(), uploadInfo.getOwnerBy());
					}
					uploadCallback.onProgress(uploadInfo, 100, FileInfoResponse.getSize(), FileInfoResponse.getSize());
				} else {
					LogUtil.e(TAG,"FileClientV2 getFileInfo() is null");
				}
				uploadCallback.onSuccess(uploadInfo, FileInfoResponse);
			} catch (Exception e) {
				uploadCallback.onFailure(uploadInfo, e);
			}
		}
	    
		@Override
		public void onBeginUploadPartByIndex(String fileId, String index) {
			DAOFactory.instance(context).getUploadFileDao().updateCurrentIndex(fileId, ownerID, index);
		}
		@Override
		public void onFinishUploadPartByIndex(String fileId, String index) {
		}
		
		@Override
		public void onUploadStoped() {
			isStoped = true;
			DAOFactory.instance(context).getUploadFileDao().updateUploadState(uploadInfo.getId(), uploadInfo.getOwnerId(), Constant.TRANSLATE_IS_STOPED);
			AlbumUploadTaskManager.instance().removeTask(AlbumUploadTask.this);
			ClientException e = new ClientException(ErrorConstant.UPLOAD_TASK_STOPED, "stoped upload task");
			uploadCallback.onFailure(uploadInfo, e);
		}
		
		@Override
		public void onCancleUpload(String fileId, String ownerId) {
		}
		@Override
		public void onCancleSuccess(String fileId, String ownerId) {
			DAOFactory.instance(context).getUploadFileDao().updateUploadState(uploadInfo.getId(), uploadInfo.getOwnerId(), Constant.TRANSLATE_IS_FAILURED);
		}
		@Override
		public void onCancleFail(String fileId, String ownerId) {
			// TODO Auto-generated method stub
		}
	    

		@Override
		public void preper(String identity) {
			oldProgress = 0;
			progress = 0;
		}
		@Override
		public void onStart(String identity) {
			LogUtil.i(TAG,"upload started!");
			uploadInfo = DAOFactory.instance(context).getUploadFileDao().getUploadFileFileInfoBySha1(identity, folderID, ownerID);
			if(uploadInfo != null) {
				fileId = uploadInfo.getId();
				uploadCallback.onStart(uploadInfo);
				LogUtil.d(TAG,"start record by identity is exits!");
			} else {
				LogUtil.d(TAG,"start record by identity is not exits!");
			}
		}
		@Override
		public void onProgres(long bytesWritten, long totalSize) {
			if (AlbumUploadTask.this.isCancel && null != uploadThread) {
				uploadThread.cancelPartsUpload();
			}
			oldProgress = (bytesWritten * 100 / totalSize);
			if (11 > (int)oldProgress) {
				oldProgress = (int)oldProgress + 11; 
			} else {
				if ((int)progress != (int)oldProgress) {
					progress = oldProgress;
					DAOFactory.instance(context).getUploadFileDao().updateProgress(fileId, ownerID, progress);
					uploadCallback.onProgress(uploadInfo, (int)progress, (long)((long)bytesWritten * (progress * 0.01)), totalSize);// onProgress
				}
			}
		}
		@Override
		public void onSuccess(String fileID, String ownerId, FileInfoResponseV2 FileInfoResponse) {
			LogUtil.i(TAG, "[" + filePath + "]onSuccess()");
			AlbumUploadTaskManager.instance().removeTask(AlbumUploadTask.this);
			DAOFactory.instance(context).getUploadFileDao().deleteFile(uploadInfo.getId(),uploadInfo.getOwnerBy());
			FileInfoResponseV2 resposeObject = null;
			try {
				if(FileInfoResponse == null) {
					if(PublicTools.isAuthiorzationGotoTimeout(context)){
						PublicTools.reGetTokenByLoginInBanck(context);
					}
					resposeObject = FileClientV2.getInstance()
							.getFileInfo(ownerID,
									fileID, 
									ShareDriveApplication.getInstance().getAuthorization());
				} else {
					resposeObject = FileInfoResponse;
				}
				if(resposeObject != null) {
					int flag = DAOFactory.instance(context).getFileDao().addIfNotExist(resposeObject);
					if(flag == 0) {
						DirectoryUtil.deleteFileThumbnailPath(context, resposeObject.getOwnerBy(), resposeObject.getId(),resposeObject.getName());
					}
				} else {
					LogUtil.e(TAG,"FileClientV2 getFileInfo() is null");
				}
				uploadCallback.onSuccess(uploadInfo, resposeObject);
			} catch (ClientException e) {
				uploadCallback.onFailure(uploadInfo, e);
			}
		}
		@Override
		public void onOperationFailure(String fileID, Throwable t) {
			LogUtil.e(TAG, "[" + filePath + "]" + t.getLocalizedMessage());
			DAOFactory.instance(context).getUploadFileDao().updateUploadState(uploadInfo.getId(), uploadInfo.getOwnerId(), Constant.TRANSLATE_IS_FAILURED);
			AlbumUploadTaskManager.instance().removeTask(AlbumUploadTask.this);
			uploadCallback.onFailure(uploadInfo, t);
		}

	};
	
	IidentityCallback fileSha1Callback = new IidentityCallback() {
		@Override
		public void onSuccess(String identity) {
			LogUtil.i(TAG,"File MD5 Identity: " + identity);
		}
		
		@Override
		public void onStart() {
			Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
            intent.setClass(context, MainFrameActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
            PendingIntent p = PendingIntent.getActivity(context, 0, intent, 0);
            mNotification.setAutoCancel(false);
            mNotification.setTicker(context.getResources().getString(R.string.upload_Notification_title));
            mNotification.setContentIntent(p);
            mNotification.setContentTitle(uploadFile.getName());
            mNotification.setProgress(100, (int) 0, false);
            mNotification.setContentText(context.getResources().getString(R.string.upload_Notification_preper_date));
            mNotificationManager.notify(notificationID, mNotification.build());
		}
		
		@Override
		public void onProgress(int currentProgress, long currentSize, long maxSize) {

		}

		@Override
		public void onFailure(Throwable t) {
			LogUtil.e(TAG, "[" + filePath + "]" + t.getLocalizedMessage());
		}
	};
	
	ITCallbackObserver<UploadObject, FileInfoResponseV2> uploadCallback = new ITCallbackObserver<UploadObject, FileInfoResponseV2>();
	
	ITCallback<UploadObject, FileInfoResponseV2> nififyCallback = new ITCallback<UploadObject, FileInfoResponseV2>() {
        
        @Override
        public void onSuccess(UploadObject request,FileInfoResponseV2 successItem) {
            mNotification.setContentText(uploadFile.getName()+ "  "+ context.getResources().getString(R.string.fileListadapter_upload_success));
            mNotificationManager.notify(notificationID, mNotification.build());
            mNotificationManager.cancel(notificationID);
            DAOFactory.instance(context).getUploadFileDao().deleteNotify(notificationID);
        }
        
        @Override
        public void onStart(UploadObject request) {
            LogUtil.i(TAG, "uploadShareFile start..." + "notificationID:" + notificationID);
        }
        
        @Override
        public void onProgress(UploadObject request, int currentProgress, long currentSize, long maxSize) {
            mNotification.setContentTitle(uploadFile.getName());
            mNotification.setProgress(100, (int) currentProgress, false);
            mNotification.setContentText(context.getResources().getString(R.string.upload_Notification_title) + "    " + (int) currentProgress + "%");
            mNotificationManager.notify(notificationID, mNotification.build());
        }
        
        @Override
        public void onFailure(UploadObject request, Throwable t) {
            LogUtil.e(TAG, "uploadShareFile... onFailure:" + "notificationID:" + notificationID);
            mNotification.setContentText(uploadFile.getName()+ "  "+ context.getResources().getString(R.string.fileListadapter_upload_failed));
            mNotificationManager.notify(notificationID, mNotification.build());
            mNotificationManager.cancel(notificationID);
            DAOFactory.instance(context).getUploadFileDao().deleteNotify(notificationID);
        }
    };
    
	public AlbumUploadTask(Context context, String ownerId, String folderID,
			String filePath, ITCallback<UploadObject, FileInfoResponseV2> uploadCallback) {
		fileinfo = new FileInfo();
		random = new Random();
		this.priority = Math.abs(random.nextInt() % 10);
		this.id = filePath;
		this.context = context;
		this.ownerID = ownerId;
		this.folderID = folderID;
		this.authorization = ShareDriveApplication.getInstance().getAuthorization();
		this.filePath = filePath;
		this.isCancel = false;
		File file = new File(filePath);
		fileinfo.setName(file.getName());
		fileinfo.setParent(folderID);
		fileinfo.setLoctPath(filePath);
		if(uploadCallback != null) {
			this.uploadCallback.registerCallback(uploadCallback);
		}
		this.uploadType = Constant.UPLOAD_TYPE_ALBUM;

		uploadFile = new File(filePath);
		
		//init notification manager
        this.uploadCallback.registerCallback(nififyCallback);
		Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setClass(context, MainFrameActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        PendingIntent p1 = PendingIntent.getActivity(context, 0, intent, 0);
		mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mNotification = new NotificationCompat
        		.Builder(context)
        		.setSmallIcon(R.drawable.icon_logo)
        		.setContentTitle(uploadFile.getName())
        		.setContentText(context.getResources().getString(R.string.upload_Notification_title));
        mNotification.setSmallIcon(R.drawable.icon_logo);
        mNotification.setContentTitle(context.getResources().getString(R.string.stor_box_get_data) + uploadFile.getName());
        mNotification.setAutoCancel(false);
        mNotification.setContentIntent(p1);
        mNotification.setProgress(100, 100, true);
        mNotificationManager.notify(notificationID, mNotification.build());
        DAOFactory.instance(context).getUploadFileDao().insertNotify(notificationID);
        
        Intent startIntent = new Intent(ReceiverConstent.ALBUM_TASK_NEW_INSTANCE_ACTION);
        startIntent.putExtra(ReceiverConstent.ALBUM_TASK_NEW_INSTANCE_DATA_1, filePath);
        context.sendBroadcast(startIntent);
		
	}
	
	public String getId() {
		return id;
	}
	
	public String getFolderID() {
		return folderID;
	}
	
	public String getFilePath() {
		return filePath;
	}
	
	@Override
	public int getPriority() {
		// TODO Auto-generated method stub
		return priority;
	}
	
	@Override
	public void setPriority(int priority) {
		// TODO Auto-generated method stub
		this.priority = priority;
	}
	
	@Override
	public void setTipTopPriority() {
		// TODO Auto-generated method stub
		this.priority = Integer.MAX_VALUE;
	}
	
	public void cancelUploadTask() {
		this.isCancel = true;
		AlbumUploadTaskManager.instance().removeTask(this);
	}

	@Override
	public void run() {
		try {
			runFilePathUpload();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AlbumUploadTask other = (AlbumUploadTask) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}
	
	public String getFileEnDir() {
		return fileEncDir;
	}
	public void setFileEnDir(String fileEnDir) {
		this.fileEncDir = fileEnDir;
	}
	//callback
	public void setCallback(ITCallback<UploadObject, FileInfoResponseV2> callback) {
		if(callback != null) {
			this.uploadCallback.registerCallback(callback);
		}
	}
	
	public void removeCallback(ITCallback<UploadObject, FileInfoResponseV2> callback) {
		if(callback != null) {
			this.uploadCallback.unRegisterCallback(callback);
		}
	}
	
	private void runFilePathUpload() {
		try {
			LogUtil.i(TAG, "[" + filePath + "]" + " runFilePathUpload... ");
			FileSmartUploadRequestV2 frRequest = new FileSmartUploadRequestV2();
			frRequest.setAuthorization(authorization);
			frRequest.setFilePath(filePath);
			// frRequest.setFileUniqueID("123456789");
			frRequest.setOwnerID(ownerID);
			frRequest.setParentId(folderID);
			
			if(uploadFile != null && uploadFile.exists()) {
				identityTool = new FileMD5Identity(filePath, fileSha1Callback);
				String primaryIdentity = this.identityTool.computeIdentity();
				if (StringUtil.isNotBlank(primaryIdentity) && !isStoped) {
					frRequest.setPrimaryIdentity(primaryIdentity);
					if(frRequest.getSize() > Constant.MD5BLOCK_KB_SIZE) {
						identityTool = new PartFileMD5Identity(filePath, 0, Constant.MD5BLOCK_KB_SIZE);
						String extenalIndetity = this.identityTool.computeIdentity();
						frRequest.setExtenalIdentity(extenalIndetity);
					} else if(frRequest.getSize() > Constant.MD5BLOCK_B_SIZE){
						identityTool = new PartFileMD5Identity(filePath, 0, Constant.MD5BLOCK_B_SIZE);
						String extenalIndetity = this.identityTool.computeIdentity();
						frRequest.setExtenalIdentity(extenalIndetity);
					}
					uploadThread = new FileSmartUploadV4(frRequest, fileUploadCallBackV2);
					uploadThread.startUpload();
				} else {
					ClientException e = new ClientException(
							ClientExceptionRelateHandler.CLIENT_EXCEPTION_OCCURED, 
							"file sha1 is null!");
					LogUtil.e(TAG, "[" + filePath + "]" + e.getLocalizedMessage());
					AlbumUploadTaskManager.instance().removeTask(AlbumUploadTask.this);
					uploadCallback.onFailure(uploadInfo, e);
				}
			} else {
				DAOFactory.instance(context).getAlbumDao().deleteAlbumByPath(filePath);
				ClientException e = new ClientException("album file not exists!");
				AlbumUploadTaskManager.instance().removeTask(AlbumUploadTask.this);
				uploadCallback.onFailure(uploadInfo, e);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			LogUtil.e(TAG, "[" + filePath + "]" + e.getLocalizedMessage());
			AlbumUploadTaskManager.instance().removeTask(AlbumUploadTask.this);
			uploadCallback.onFailure(uploadInfo, e);
		}
	}

	public boolean isTaskStoped() {
		return isStoped;
	}
	
	public void stopUploadTask() {
		isStoped = true;
		if(uploadThread != null){
			uploadThread.stopUpload();
		}
	}
}
